#include "SoundDuplex.h"
#include "RTPTransfer.h"
#include <cassert>
#include <rtpudpv4transmitter.h>
#include <rtpsessionparams.h>
#include <rtpipv4address.h>
#include <iostream>

void checkerror( int rtperr )
{
	assert ( rtperr >= 0 );
}

int main(int argc, char* argv[])
{
	if (argc < 4)
	{
		std::cout << "ipsound [source port] [destination port] [destination IP]" << std::endl;
		return -1;
	}

	WSADATA dat;
	WSAStartup( MAKEWORD(2,2), &dat );

	//CoInitializeEx(0,COINIT_MULTITHREADED);

	MutexBuffer sendBuf( 32000, "sendBuf" );
	MutexBuffer recieveBuf( 32000, "recieveBuf");

	ipsound::SoundDuplex sound( &recieveBuf, &sendBuf, GetConsoleWindow() );

	HANDLE bufEvent = CreateEvent( 0, false, false, 0 );

	ipsound::RTPTransfer transfer( &recieveBuf );
	transfer.SetBufEvent( bufEvent, sound.GetMinimumPlaySize() * 2 );

	double samplesPerSec = 8000;
	size_t packetSize = 1000;
	unsigned short srcPort = atoi(argv[1]), dstPort = atoi(argv[2]);

	unsigned int dstIp = inet_addr( argv[3] );
	assert( dstIp != INADDR_NONE );
	dstIp = ntohl( dstIp );

	RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;

	sessparams.SetOwnTimestampUnit( 1.0 / samplesPerSec );
	sessparams.SetAcceptOwnPackets( true );
	transparams.SetPortbase( srcPort );
	int status = transfer.Create( sessparams, &transparams );
	checkerror( status );

	RTPIPv4Address addr( dstIp, dstPort );

	status = transfer.AddDestination( addr );
	checkerror( status );

	transfer.SetDefaultMark(false);
	transfer.SetDefaultPayloadType(0);
	transfer.SetDefaultTimestampIncrement( (uint32_t)(packetSize / samplesPerSec) );

	sound.StartCapture();
	bool soundPlayStarted = false;
	void* buf = malloc(packetSize);

	while (true)
	{
		size_t read = sendBuf.Read(buf, packetSize);
		if (read > 0)
		{
			transfer.SendPacket(buf, read);
		}

		if(!soundPlayStarted)
		{
			switch( WaitForSingleObject(bufEvent, 0) )
			{
			case WAIT_OBJECT_0:
				sound.StartPlay();
				soundPlayStarted = true;
				break;
			default:
				continue;
			}
		}

		RTPTime::Wait( packetSize / (samplesPerSec * 2) );
	}

	CloseHandle(bufEvent);

	//CoUninitialize();

	WSACleanup();
	return 0;
}